package configuration;

import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.Map.Entry;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


public class ConfigurationService {
   private static HashMap<String, List<ConfigurationItem>>  configSectionMap;
   
   private static final String TAG_SECTION = "Section";
   private static final String TAG_TAG = "Tag";
   private static final String TAG_VALUE = "Value";
   private static final String FILE_EXT = ".xml";
   
   
   static{
	  initialize();
   }
	
   private static void initialize(){
	   configSectionMap = new HashMap<String, List<ConfigurationItem>>();
	   
	   String rootDirectoryName = getDirectoryRoot();
	   if (rootDirectoryName == null){
	      System.out.println("Directory is null");
	   }
	   else{
		  File rootDirectory = new File(rootDirectoryName);
	      if (!rootDirectory.isDirectory()){
	         System.out.println("Not a valid directory name");
	      }
	      else{ 
    	     File[] files = rootDirectory.listFiles(new FilenameFilter()
             {
                public boolean accept(File f, String name)
                {
                  return name.toLowerCase().endsWith(FILE_EXT);
                }
             });
    	     for (int k = 0; k < files.length; k++)
             {
               if (files[k].isFile() != true){
                 continue;
               }
               String fileName = files[k].getAbsolutePath();
               String keyName = files[k].getName().substring(0, files[k].getName().length() - 4);
               populateConfigSectionMap(fileName, keyName);
               
             }   
	      }
	   }
   }
	
   public static List<ConfigurationItem> getConfiguration(String sectionName)
   {
	   if (sectionName == null || "".equals(sectionName)){
		   return null;
	   }
	   
	   Set<Entry<String, List<ConfigurationItem>>> sectionSet = configSectionMap.entrySet();
	   for (Entry<String, List<ConfigurationItem>> section : sectionSet) {
		   if (sectionName.toLowerCase().equals(section.getKey())){
			   return section.getValue();
		   }
	   }	
	   return null;
   }
   
   public static String getConfigurationValue(String sectionName, String tagName)
   {
	   if (sectionName == null || "".equals(sectionName) || tagName == null || "".equals(tagName)){
		   return null;
	   }
	   List<ConfigurationItem> itemList = getConfiguration(sectionName);
	   for (ConfigurationItem configurationItem : itemList) {
		   if (tagName.equals(configurationItem.getTagName())){
			   return configurationItem.getTagValue();
		   }
	   }
	   return null;
   }
   
   private static String getDirectoryRoot()
   {
     String retval = System.getProperty("configuration.configurationRootDirectory");
     if (retval == null)
     {
      System.out.println("The [configuration.configurationRootDirectory] system property is not available");
     }
     return retval;
   }

   private static Document CreateDocumentFromURL(String URL)
   {
     Document dom = null;
     DocumentBuilder documentBuilder = null;
     DocumentBuilderFactory theDocumentBuilderFactory = null;
     try
     {
       theDocumentBuilderFactory = DocumentBuilderFactory.newInstance();
       if (theDocumentBuilderFactory != null){
    	   documentBuilder = theDocumentBuilderFactory.newDocumentBuilder();
       }
       if (documentBuilder != null){
    	   dom = documentBuilder.parse(new File(URL)); 
       }
       if (dom == null){
         System.out.println("Null Document for XML configuration file [" + URL + "]");
       }
     }
     catch (Throwable e)
     {
       System.out.println("Unable to create Document for XML configuration file [" + URL + "]");
     }
     return dom;
   }
   
   private static void populateConfigSectionMap(String fileName, String keyName){
       Document dom = CreateDocumentFromURL(fileName);
       NodeList nl = dom.getElementsByTagName(TAG_SECTION);
       String sectionName = null;
       for (int i = 0; i < nl.getLength(); i++)
       {
           Node node = nl.item(i);
           Node child = node.getFirstChild();
           if (child != null)
           {
             sectionName = child.getNodeValue().trim();
           }
           List<ConfigurationItem> configurationItemList = new ArrayList<ConfigurationItem>();
           NodeList allNodesInThisSection = node.getChildNodes();
           int j = 0;
           if (allNodesInThisSection != null)
           {
             while (j < allNodesInThisSection.getLength())
             {
               Node tagValueNode = allNodesInThisSection.item(j);
               if (tagValueNode != null)
               {
                 String nodeName = tagValueNode.getNodeName();

                 if ((nodeName != null) && (nodeName.equals(TAG_TAG)))
                 {
                   String tagName = tagValueNode.getFirstChild().getNodeValue();
                   Node ValueNode = findNode(TAG_VALUE, tagValueNode.getChildNodes());

                   String tagValue = "";
                   if (ValueNode != null)
                   {
                     if (ValueNode.getFirstChild() != null)
                     {
                       tagValue = ValueNode.getFirstChild().getNodeValue();
                     }
                   }

                   ConfigurationItem theConfigurationItem = new ConfigurationItem();
                   if (tagName != null)
                   {
                     theConfigurationItem.setTagName(tagName.trim());
                   }
                   if (tagValue != null)
                   {
                     theConfigurationItem.setTagValue(tagValue.trim());
                   }
                   configurationItemList.add(theConfigurationItem);
                 }
               }
               j++;
             }
           }
           if (sectionName == null){
               continue;
           }    
           configSectionMap.put(sectionName.toLowerCase(), configurationItemList);
		}
   }	   
   
   private static Node findNode(String tagName, NodeList theNodeList)
   {
     Node foundNode = null;
     if (theNodeList != null)
     {
       int i = 0;
       while ((i < theNodeList.getLength()) && (foundNode == null))
       {
         Node node = theNodeList.item(i);
         if (node == null)
         {
           System.out.println("Failed to get Node");
         }
         else
         {
           String nodeName = node.getNodeName();
           if (nodeName == null)
           {
             System.out.println("Failed to get Node Name");
           }
           else if (nodeName.equals(tagName))
           {
             foundNode = node;
           }
         }
         i++;
       }
     }
     return foundNode;
   }
   
	/**
	 * test
	 */
	public static void main(String[] args) {
		System.out.println(ConfigurationService.getConfigurationValue("TestSection2", "TestTag22"));
	}

}
